package com.ztesoft.web.checkup.service.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;

import com.ztesoft.core.db.ds.DynamicDataSourceManager;
import com.ztesoft.core.spring.context.SpringApplicationContextHolder;
import com.ztesoft.framework.exception.BaseAppException;
import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.framework.util.DateUtils;
import com.ztesoft.framework.util.Utils;
import com.ztesoft.web.baseconfig.db.arg.DmTargetTableArg;
import com.ztesoft.web.baseconfig.db.dao.DmTargetTableDao;
import com.ztesoft.web.baseconfig.db.po.DmPlanPO;
import com.ztesoft.web.baseconfig.db.po.DmSrcTablePO;
import com.ztesoft.web.baseconfig.db.po.DmStrategyPO;
import com.ztesoft.web.baseconfig.db.po.DmTargetTablePO;
import com.ztesoft.web.checkup.service.CheckUpStrategy;
import com.ztesoft.web.common.DMSConstant;
import com.ztesoft.web.common.Util;
import com.ztesoft.web.common.customdb.SQLHelper;
import com.ztesoft.web.common.customdb.dao.DmTaskStageCustomDao;
import com.ztesoft.web.common.customdb.dao.dto.DmTaskStageDto;
import com.ztesoft.web.resourcecheck.ResourceCheckJob;
import com.ztesoft.web.syncbaseinfo.service.BaseInfoService;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskDao;
import com.ztesoft.web.taskgenerator.db.po.DmTaskPO;


/**
 * 体检策略<br>
 * oracle分区归档 索引部分需要人工介入，有更好的方法欢迎补充
 * 
 * @author <a href="mailto:lin.weibin@zte.com.cn">lin.wb</a> 2016年5月19日 下午7:13:20
 * @version 1.0
 */
public class CheckUpStrategyPartition  implements CheckUpStrategy {
	
	private static final ZTEsoftLogManager LOGGER = ZTEsoftLogManager
	            .getLogger(CheckUpStrategyPartition.class);
	
	@Autowired
	private DynamicDataSourceManager dynamicDataSourceManager;
	
	@Autowired
	private BaseInfoService baseInfoService;
	
	@Autowired
	private DmTaskStageCustomDao taskStageCustomDao;

	@Autowired
	private ResourceCheckJob resourceCheckJob;
	
	@Autowired
	private DmTaskDao taskDao;
	
	@Autowired
	private DmTargetTableDao targetTableDao;
	
	public String checkUp(DmPlanPO planPO, DmTaskPO taskPO, DmStrategyPO strategyPO, DmSrcTablePO srcTablePO) {
		String checkState = "50E";
		LOGGER.debug("|查询任务环节列表|strategyId={0},taskId={1}", strategyPO.getDmStrategyId(), taskPO.getDmTaskId());
		List<DmTaskStageDto> taskStageList = taskStageCustomDao.selectTaskStageList(taskPO.getDmTaskId(), 
				strategyPO.getDmStrategyId(), DMSConstant.STAGE_CHECKUP, DMSConstant.Status.PENDING.getState());
		LOGGER.info("|查询待体检任务环节列表|\r\n{0}",taskStageList);
		if (taskStageList.isEmpty()) {
			return checkState;//
		}
		String[] dbConfig = null;
		try {
			dbConfig = baseInfoService.getDbConfig(srcTablePO.getDbLinkId(), srcTablePO.getDbUserName());
		} catch (BaseAppException e1) {
		}
		DataSource dataSource = dynamicDataSourceManager.getDruidDataSource(srcTablePO.getDbLinkId()+srcTablePO.getDbUserName(), dbConfig);
		if (DMSConstant.ORACLE.equals(dbConfig[0])) { //
			for (DmTaskStageDto taskStagePO : taskStageList) {				
				taskStagePO.setTaskStartTime((taskStagePO.getTaskStartTime()!=null)?null:DateUtils.getDBCurrentTime());
				taskStagePO.setTaskEndTime(null);//避免带入条件
				taskStagePO.setCheckDataSize(null);
				taskStagePO.setErrorDesc(null);
				taskStagePO.setStage(null);
				taskStageCustomDao.updateTaskStageState(taskStagePO);
			}
			
			PreparedStatement ps = null;
			ResultSet rst = null;
			Connection conn = null;
			List<String> partList = null;
			String sql = "SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS where table_name=?";
			try {
				partList = new ArrayList<String>(5);
				conn = DataSourceUtils.getConnection(dataSource);
				ps = conn.prepareStatement(sql);
				ps.setString(1, StringUtils.upperCase(srcTablePO.getTableName()));//单表
				rst = ps.executeQuery();
				while (rst.next()) {
					partList.add(rst.getString(1));
				}
			} catch (SQLException e) {
				LOGGER.error("", e);
				DmTaskStageDto po = taskStageList.get(0);
				po.setTaskStartTime(null);
				po.setState("00F");
				po.setStateDate(DateUtils.getDBCurrentTime());
				po.setTaskEndTime(DateUtils.getDBCurrentTime());
				po.setCheckObjName(null);//更新策略下所有
				po.setStage(null);
				po.setErrorDesc("查询分区异常"+e.toString());
				taskStageCustomDao.updateTaskStageState(po);//
				return "00F";
			} finally {
				JdbcUtils.closeStatement(ps);
				JdbcUtils.closeResultSet(rst);
				DataSourceUtils.releaseConnection(conn, dataSource);
			}
			LOGGER.info("查询分区集合|{0}|",partList);
			//查询记录
			int resultCount = 0;
			try {
				conn = DataSourceUtils.getConnection(dataSource);
				sql = SQLHelper.selectCount(srcTablePO.getTableName(), null, null, "oracle");
				ps = conn.prepareStatement(sql);
				rst = ps.executeQuery();
				if (rst.next()) {
					resultCount = rst.getInt(1);
				}
			} catch (SQLException e) {
				LOGGER.error("", e);
			} finally {
				JdbcUtils.closeStatement(ps);
				JdbcUtils.closeResultSet(rst);
				DataSourceUtils.releaseConnection(conn, dataSource);
			}
			LOGGER.info("源表{0}数据count:{1}",srcTablePO.getTableName(), resultCount);
			DmTargetTableArg dmTargetTableArg = new DmTargetTableArg();
			DmTargetTableArg.DmTargetTableCriteria targetTableCriteria = dmTargetTableArg.createCriteria();
			targetTableCriteria.andSourceDataIdEqualTo(srcTablePO.getSourceDataId());
			DmTargetTablePO targetPO = targetTableDao.selectByArg(dmTargetTableArg).get(0);
			List<String> sqlList = new ArrayList<String>(5);
			for (String partStr : partList) {
				String changeSql = "alter table $source_table_name exchange partition  $partition_name with table $dest_table_name";
				changeSql = changeSql.replace("$source_table_name", srcTablePO.getTableName());
				changeSql = changeSql.replace("$partition_name", partStr);
				changeSql = changeSql.replace("$dest_table_name", targetPO.getTableName());
				sqlList.add(changeSql);
			}
			if (Utils.notEmpty(sqlList)) {
				try {
					conn = DataSourceUtils.getConnection(dataSource);
					for (String changeSql : sqlList) {
						ps = conn.prepareStatement(changeSql);
						ps.execute();
					}
				} catch (SQLException e) {
					LOGGER.error("置换表分区异常", e);
					DmTaskStageDto po = taskStageList.get(0);
					po.setTaskStartTime(null);
					po.setState("00F");
					po.setStateDate(DateUtils.getDBCurrentTime());
					po.setTaskEndTime(DateUtils.getDBCurrentTime());
					po.setCheckObjName(null);//更新策略下所有
					po.setStage(null);
					po.setErrorDesc("置换表分区异常"+e.toString());
					taskStageCustomDao.updateTaskStageState(po);//
					return "00F";
				} finally {
					JdbcUtils.closeStatement(ps);
					DataSourceUtils.releaseConnection(conn, dataSource);
				}
			}
			
			LOGGER.info("置换分区成功");
			//查询记录 再次查询确认数据
			int cgResult = 0;
			try {
				conn = DataSourceUtils.getConnection(dataSource);
				sql = SQLHelper.selectCount(srcTablePO.getTableName(), null, null, "oracle");
				ps = conn.prepareStatement(sql);
				rst = ps.executeQuery();
				if (rst.next()) {
					cgResult = rst.getInt(1);
					if (cgResult != 0) {
						throw new SQLException("置换分区异常，分区未置换成功");
					}
				}
			} catch (SQLException e) {
				LOGGER.error("", e);
				DmTaskStageDto po = taskStageList.get(0);
				po.setTaskStartTime(null);
				po.setState("00F");
				po.setStateDate(DateUtils.getDBCurrentTime());
				po.setTaskEndTime(DateUtils.getDBCurrentTime());
				po.setCheckObjName(null);//更新策略下所有
				po.setStage(null);
				po.setErrorDesc("置换表分区未能成功"+e.toString());
				taskStageCustomDao.updateTaskStageState(po);//
				return "00F";
			} finally {
				JdbcUtils.closeStatement(ps);
				JdbcUtils.closeResultSet(rst);
				DataSourceUtils.releaseConnection(conn, dataSource);
			}
			//更新数据
			for (DmTaskStageDto po : taskStageList) {	
				po.setTaskStartTime(null);
				po.setState("00A");
				po.setStateDate(DateUtils.getDBCurrentTime());
				po.setTaskEndTime(DateUtils.getDBCurrentTime());
				po.setStage(null);
				po.setErrorDesc(null);
				po.setIsCheck(0);//默认审批通过
				po.setCheckCount(resultCount);
				po.setTotalRecordCount(resultCount);
				po.setCheckDataSize(Util.divValue2BigDecimal(srcTablePO.getOneRecordSize(), resultCount, 2));
				po.setTotalDataSize(po.getCheckDataSize());
				taskStageCustomDao.updateTaskStageState(po);//
			}
			checkState = "50E";
		} else if (DMSConstant.INFORMIX.equals(dbConfig[0]) || DMSConstant.MYSQL.equals(dbConfig[0])) {
			CheckUpStrategy checkUpStrategy = SpringApplicationContextHolder.getBean(CheckUpStrategyCondition.class);
			return checkUpStrategy.checkUp(planPO, taskPO, strategyPO, srcTablePO);
		}
		return checkState;
	}
	
}
